package org.example.filter;

import cn.hutool.json.JSONUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.example.model.LoginUser;
import org.example.utils.JwtUtil;
import org.example.utils.Opt;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * TokenHandlerInterceptor 是一个拦截器，用于处理请求中的认证令牌（Token）
 * 它实现了 HandlerInterceptor 和 Ordered 接口，用于在请求处理前进行拦截和处理
 * 同时使用 @Component 注解将其声明为 Spring 组件，使用 @Slf4j 注解注入日志对象
 */
@Component
@Slf4j
public class TokenHandlerInterceptor implements HandlerInterceptor, Ordered {



    /**
     * preHandle 方法在请求处理前被调用，用于验证请求中的 JWT 令牌
     * @param request 当前 HTTP 请求对象
     * @param response 当前 HTTP 响应对象
     * @param handler 请求处理的方法或类
     * @return 如果验证通过返回 true，否则返回 false 并设置响应状态码为 401
     * @throws Exception 可能抛出的异常
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        // 从请求头中获取 Authorization 信息，并使用 Opt 进行包装
        Opt<String> authorization = Opt.of(request.getHeader("Authorization"));
        // 检查 Authorization 是否存在或为空
        if(!authorization.isPresent() || authorization.get().isEmpty()) {
            log.error("Authorization header is missing or empty"); // 记录错误日志
            response.sendError(401, "Authorization header is missing or empty"); // 发送 401 错误响应
            return false; // 验证失败，返回 false
        }
        // 从 Authorization 中提取令牌（去除 "Bearer " 前缀）
        String token = authorization.get().substring(7);
        // 使用 JwtUtil 解析 JWT 令牌获取 Claims
        Claims claims = JwtUtil.parseJWT(token);
        // 从 Claims 中获取主题信息（通常是用户信息）
        String subject = claims.getSubject();
        // 将主题信息转换为 LoginUser 对象
        LoginUser loginUser = JSONUtil.toBean(subject, LoginUser.class);
        // 将登录用户信息存入请求属性中，供后续使用
        request.setAttribute("loginUser", loginUser);
        return true; // 验证成功，返回 true
    }


    /**
     * 获取拦截器的执行顺序值
     * @return 返回拦截器的执行顺序，值越小优先级越高
     */
    @Override
    public int getOrder() {
        return 9; // 设置拦截器执行顺序为 9
    }
}
